﻿using System;
using System.Collections.Generic;
using System.Linq;
using FacebookXmpp.Parse;
using FacebookXmpp.Stanzas;

namespace FacebookXmpp
{
	internal class StreamHandlers 
	{
		private readonly Dictionary<StanzaListenCriteria, Stanza> _handlers = new Dictionary<StanzaListenCriteria, Stanza>();
		private readonly Dictionary<StanzaListenCriteria, Stanza> _addList = new Dictionary<StanzaListenCriteria, Stanza>();
		private readonly List<Stanza> _removeList = new List<Stanza>();

		public Dashboard Dashboard;

		internal void ProcessResponse( MessageData received, XmlStream xmlStream)
		{
			UpdateList();

			foreach (var stanza in _handlers.Where( mc => mc.Key.Match( received ) ))
				stanza.Value.ProcessResponse( received, xmlStream, this );
		}

		internal IEnumerable<object> ForEach( Func<Stanza, object> action )
		{
			UpdateList();

			foreach (var stanza in _handlers.Values)
				yield return action( stanza );
		}

		internal bool Any()
		{
			UpdateList();
			return _handlers.Any();
		}

		internal bool AnyAllowOpen
		{
			get
			{
				UpdateList();
				return _handlers.Any( kvp => kvp.Key.AllowOpen );
			}
		}

        internal void Add(Stanza stanza)
        {
            _addList.Add(stanza.ListenFor, stanza);
        }

        internal void Add(Stanza stanza, StanzaListenCriteria listenFor)
        {
            _addList.Add(listenFor, stanza);
        }

		internal void Remove( Stanza stanza )
		{
			_removeList.Add( stanza );
		}
		
		internal int LongestResponseTimeout
		{
			get
			{
				return _handlers.Max( kvp => kvp.Key.ResponseTimeMilliseconds );
			}
		}

		private void UpdateList( )
		{
			foreach (var entry in _addList)
				_handlers.Add( entry.Key, entry.Value );
			
			foreach (var remove in _removeList)
			{
				var entry = _handlers.Where( kvp => kvp.Value == remove ).First();
				_handlers.Remove( entry.Key );
			}

			_addList.Clear();
			_removeList.Clear();
		}

	}
}
